package com.tianji.learning.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.dto.course.CourseFullInfoDTO;
import com.tianji.api.dto.leanring.LearningLessonDTO;
import com.tianji.api.dto.leanring.LearningRecordDTO;
import com.tianji.api.dto.leanring.LearningRecordFormDTO;
import com.tianji.common.autoconfigure.mq.RabbitMqHelper;
import com.tianji.common.constants.MqConstants;
import com.tianji.common.exceptions.BizIllegalException;
import com.tianji.common.exceptions.DbException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.DateUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.po.LearningLesson;
import com.tianji.learning.domain.po.LearningRecord;
import com.tianji.learning.domain.po.PointsRecord;
import com.tianji.learning.enums.LessonStatus;
import com.tianji.learning.enums.SectionType;
import com.tianji.learning.mapper.LearningRecordMapper;
import com.tianji.learning.mq.message.SignInMessage;
import com.tianji.learning.service.ILearningLessonService;
import com.tianji.learning.service.ILearningRecordService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.learning.utils.LearningRecordDelayTaskHandler;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;

/**
 * <p>
 * 学习记录表 服务实现类
 * </p>
 *
 * @author Aimer
 * @since 2025-11-06
 */
@Service
@RequiredArgsConstructor
public class LearningRecordServiceImpl extends ServiceImpl<LearningRecordMapper, LearningRecord> implements ILearningRecordService {

    private final ILearningLessonService iLearningLessonService;

    private final CourseClient courseClient;

    private final LearningRecordDelayTaskHandler taskHandler;

    private final RabbitMqHelper rabbitMqHelper;

    @Override
    public LearningLessonDTO queryLearningRecordByCourse(Long courseId) {
        // 获取用户id
        Long userId = UserContext.getUser();
        LambdaQueryWrapper<LearningLesson> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(LearningLesson::getCourseId,courseId);
        lambdaQueryWrapper.eq(LearningLesson::getUserId,userId);
        LearningLesson learningLesson = iLearningLessonService.getOne(lambdaQueryWrapper);
        if (learningLesson == null){
            return null;
        }
        // 查询学习记录
        List<LearningRecord> records = lambdaQuery().eq(LearningRecord::getLessonId, learningLesson.getId()).list();

        LearningLessonDTO learningLessonDTO = new LearningLessonDTO();
        learningLessonDTO.setId(learningLesson.getId());
        learningLessonDTO.setLatestSectionId(learningLesson.getLatestSectionId());
        List<LearningRecordDTO> list = BeanUtils.copyList(records, LearningRecordDTO.class);
        learningLessonDTO.setRecords(list);
        return learningLessonDTO;
    }

    @Override
    public void addLearningRecord(LearningRecordFormDTO learningRecordFormDTO) {
        // 获取当前用户id
        Long userId = UserContext.getUser();
        // 处理学习记录
        boolean finished = false;
        // 判断传入的小结是否是考试
        if (learningRecordFormDTO.getSectionType() == SectionType.EXAM.getValue()) {
           finished = handleExamRecord(learningRecordFormDTO, userId);
        }else {
            // 2.1.处理视频
            finished = handleVideoRecord(userId, learningRecordFormDTO);
        }
        if (!finished){
            // 没有新学完的小结，无需更新课表中的学习进度
            return;
        }
        // 处理课表数据
            handleLearningLessonsChanges(learningRecordFormDTO);
    }
    private void handleLearningLessonsChanges(LearningRecordFormDTO recordDTO) {
        // 查询课表
        LearningLesson learningLesson = iLearningLessonService.getById(recordDTO.getLessonId());
        if (learningLesson == null){
            throw new BizIllegalException("课程不存在，无法更新数据！");
        }
        // 判断是否有完成的小结
        boolean allLearned = false;
            // 如果有新完成的小结则需要查询课程
            CourseFullInfoDTO cInfo = courseClient.getCourseInfoById(learningLesson.getCourseId(), false, false);
            if (cInfo == null) {
                throw new BizIllegalException("课程不存在，无法更新数据！");
            }
            // 判断课程是否全部学完 已学习小节 >= 课程总小节
            allLearned = learningLesson.getLearnedSections() + 1 > cInfo.getSectionNum();

        // 5.更新课表
        iLearningLessonService.lambdaUpdate()
                .set(learningLesson.getLearnedSections() == 0, LearningLesson::getStatus, LessonStatus.LEARNING.getValue())
                .set(allLearned, LearningLesson::getStatus, LessonStatus.FINISHED.getValue())
                .setSql("learned_sections = learned_sections + 1")
                .eq(LearningLesson::getId, learningLesson.getId())
                .update();
    }
    private boolean handleVideoRecord(Long userId, LearningRecordFormDTO recordDTO) {
        // 查询是否存在旧学习记录
        LearningRecord oldLearningRecord = queryOldRecord(recordDTO.getLessonId(), recordDTO.getSectionId());

        if (oldLearningRecord == null){
            LearningRecord learningRecord = BeanUtils.copyBean(recordDTO, LearningRecord.class);
            learningRecord.setUserId(userId);
            boolean success = save(learningRecord);
            if (!success){
                throw new DbException("新增学习记录失败！");
            }
            return false;
        }

        // 存在则更新
        // 判断是否是第一次完成
        boolean finished = !oldLearningRecord.getFinished() && recordDTO.getMoment() * 2 >= recordDTO.getDuration();
        // 更新数据
        if (!finished){
            LearningRecord record = new LearningRecord();
            record.setLessonId(recordDTO.getLessonId());
            record.setSectionId(recordDTO.getSectionId());
            record.setMoment(recordDTO.getMoment());
            record.setId(oldLearningRecord.getId());
            record.setFinished(oldLearningRecord.getFinished());
            taskHandler.addLeaningRecordTask(record);
            return false;
        }
        boolean success = lambdaUpdate()
                .set(LearningRecord::getMoment, recordDTO.getMoment())
                .set(LearningRecord::getFinished, true)
                .set(LearningRecord::getFinishTime, recordDTO.getCommitTime())
                .eq(LearningRecord::getId, oldLearningRecord.getId())
                .update();
        // 发送消息获取积分
        rabbitMqHelper.send(MqConstants.Exchange.LEARNING_EXCHANGE,MqConstants.Key.LEARN_SECTION, userId);
        if(!success){
            throw new DbException("更新学习记录失败！");
        }
        // 4.3清理缓存
        taskHandler.deleteLearningRecordCache(recordDTO.getLessonId(),recordDTO.getSectionId());
        return true ;
    }

    private boolean handleExamRecord(LearningRecordFormDTO learningRecordFormDTO, Long userId) {
        // 添加考试记录
        LearningRecord learningRecord = BeanUtils.copyBean(learningRecordFormDTO, LearningRecord.class);
        learningRecord.setUserId(userId);
        learningRecord.setFinished(true);
        learningRecord.setFinishTime(learningRecordFormDTO.getCommitTime());
        boolean save = save(learningRecord);
        // 发送消息添加积分
        rabbitMqHelper.send(MqConstants.Exchange.LEARNING_EXCHANGE,MqConstants.Key.LEARN_SECTION,userId);
        if (!save){
            throw new RuntimeException("考试记录添加失败");
        }
        return true;
    }


    private LearningRecord queryOldRecord(Long lessonId, Long sectionId) {
        // 1.查询缓存
        LearningRecord learningRecordCache = taskHandler.readLearningRecordCache(lessonId, sectionId);
        // 2.如果命中直接返回
        if (learningRecordCache != null){
            return learningRecordCache;
        }
        // 3.没有命中查询数据库
        LearningRecord learningRecordDb = lambdaQuery()
                .eq(LearningRecord::getLessonId, lessonId)
                .eq(LearningRecord::getSectionId, sectionId)
                .one();
        // 4.写入缓存
        taskHandler.writeRecordCache(learningRecordDb);
        return learningRecordDb;
    }
}
